﻿using StarryEdge.Core.Device;
using StarryEdge.Core.Models;
using StarryEdge.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace StarryEdge.Devices.MeterDevice.ElectronicScales
{
    public class AND4531B : NormalDeviceBase, IDeviceInteraction<int>
    {
        private bool _disposed;
        private byte[] _cmd = Encoding.ASCII.GetBytes("Z\r\n");
        private List<byte> _cacheByte = new List<byte>(1024);

        public AND4531B(ICommunication com, IStarryEdgeLog edgeLog, Func<DeviceInfoModel, IDevice, bool> func) : base(com, edgeLog, func)
        {
        }

        public void Close()
        {
            _disposed = false;
            _com.Close();
        }

        public bool Open()
        {
            if (_com.Open())
            {
                Read();
                _disposed = true;
            }
            return false;
        }

        private double? GetAndWeight(byte[] originalbyte)
        {
            try
            {
                if (originalbyte.Length >= 15)
                {
                    byte[] bytes = new byte[0];
                    var str = Encoding.ASCII.GetString(originalbyte).Split(new char[] { '\r', '\n' }, StringSplitOptions.RemoveEmptyEntries);
                    if (str.Length > 1)
                    {
                        int count = 0;
                        for (int i = str.Length - 1; i > 0; i--)
                        {
                            //if (str[i].Length == 13 && str[i].Contains("WT,+"))
                            if (str[i].Length == 13 && str[i].Contains("WT,"))
                            {
                                count = i;
                                break;
                            }
                        }
                        bytes = Encoding.ASCII.GetBytes(str[count]);
                    }
                    else
                    {
                        bytes = Encoding.ASCII.GetBytes(str[0]);
                        if (bytes.Length < 13) return null;
                    }
                    var section1 = Encoding.ASCII.GetString(bytes, 0, 2);//WT
                    var section3 = Encoding.ASCII.GetString(bytes, 3, 1);//+
                    var section4 = Encoding.ASCII.GetString(bytes, 4, 7);//value
                    double.TryParse(section4, out double w);
                    if (section1.ToUpper() == "WT") return w;
                    //if (section1.ToUpper() == "WT" && section3.Contains("+")) return w;
                }
                return null;
            }
            catch (Exception)
            {
                return null;
            }
        }

        private void Read()
        {
            Task.Run(() =>
            {
                while (_disposed)
                {
                    try
                    {
                        _cacheByte.AddRange(_com.Receive());
                        if (_cacheByte.Count > 512)
                        {
                            _cacheByte.Clear();
                        }
                        Thread.Sleep(100);
                    }
                    catch (Exception ex)
                    {
                        _edgeLog.LogRun($"[{nameof(AND4531B)}] 异常：{ex}", Core.Enums.LogLevel.Warning);
                        if (_func.Invoke(_com.DeviceInfo, this))
                        {
                            continue;
                        }
                    }
                }
            });
        }

        public TValue ReadSingle<TValue>(int address, int length)
        {
            byte[] bytes = _cacheByte.ToArray();
            _cacheByte.Clear();
            double? value = GetAndWeight(bytes);
            return value == null ? default : (TValue)(object)value;
        }

        public bool WriteSingle(int address, object value, int length = 3)
        {
            for (int i = 0; i < length; i++)
            {
                try
                {
                    _com.Send(_cmd);
                    return true;
                }
                catch (Exception ex)
                {
                    _edgeLog.LogRun($"[{nameof(AND4531B)}] 异常：{ex}", Core.Enums.LogLevel.Warning);
                    if (_func.Invoke(_com.DeviceInfo, this))
                    {
                        return default;
                    }
                }
            }
            return false;
        }
    }
}
